#include "CUpdateTable.h"

#include "CUKeyUValueCalc.h"
#include "CppSQLite3.h"
#include <sstream>
#include <iostream>

int CUpdateTable::getTableType() const
{
	return TableUpdate;
}

int CUpdateTable::InitTable()
{
	m_tableConfigure->setTableField(CTableField("uKey", EFieldType::EFieldTypeInt, 0));
	m_tableConfigure->setTableField(CTableField("uValue", EFieldType::EFieldTypeInt, 0));

	return CTableBase::InitTable();
}

int CUpdateTable::writeLog(CLogBatchPtr logBatch)
{
	boost::lock_guard<CLogDatabase> lock(*m_logDatabase);

	try {
		// Check if we have the required components
		if (!logBatch || !m_tableConfigure || !m_logDatabase) {
			return -1; // Error: missing batch, configuration, or database
		}
		
		// Get the database connection
		CppSQLite3DB* db = m_logDatabase->getDatabaseConnection();
		if (!db) {
			return -2; // Error: no database connection
		}
		
		// Get the table name
		std::string tableName = m_tableConfigure->getTableName();
		if (tableName.empty()) {
			return -3; // Error: no table name
		}
		
		// Generate a new tUuid for this batch
		std::string newUuid = generateUUID();
		
		// Clear all existing records from the table
		int clearResult = ClearAllRecords(tableName, db);
		if (clearResult != 0) {
			return clearResult; // Error: failed to clear records
		}
		
		std::cout << "Cleared all existing records from table: " << tableName << std::endl;
		
		// Add tUuid to all records in the batch
		for (const auto& record : logBatch->GetRecords()) {
			record->AddField("uuid", newUuid);
		}
		
		return logBatch->enumLogRecord([=](CLogRecordPtr record) -> int
			{
				return writeRecord(record);
			});
		
	} catch (const CppSQLite3Exception& e) {
		// Handle SQLite exceptions
		//std::cout << "SQLite error in writeLog: " << e.errorMessage() << std::endl;
		return -4; // Error: SQLite exception
	} catch (const std::exception& e) {
		// Handle other exceptions
		std::cout << "General error in writeLog: " << e.what() << std::endl;
		return -5; // Error: general exception
	}
}

int CUpdateTable::writeRecord(CLogRecordPtr logRecord)
{
	try {
		// Check if we have the required components
		if (!logRecord || !m_tableConfigure || !m_logDatabase) {
			return -1; // Error: missing record, configuration, or database
		}
		
		// Use base class InsertRecord method
		return InsertRecord(logRecord);
		
	} catch (const CppSQLite3Exception& e) {
		// Handle SQLite exceptions
		//std::cout << "SQLite error in writeRecord: " << e.errorMessage() << std::endl;
		return -4; // Error: SQLite exception
	} catch (const std::exception& e) {
		// Handle other exceptions
		std::cout << "General error in writeRecord: " << e.what() << std::endl;
		return -5; // Error: general exception
	}
}

int CUpdateTable::beforeWriteRecord(CLogRecordPtr logRecord)
{
	CTableBase::beforeWriteRecord(logRecord);

	CUKeyUValueCalc calc(this);
	calc.CalculateUKeyUValue(logRecord);

	if (!logRecord->hasField("uKey"))
		logRecord->AddField("uKey", (uint64_t)calc.getUKey());

	if (!logRecord->hasField("uValue"))
		logRecord->AddField("uValue", (uint64_t)calc.getUValue());

	return 0;
}

int CUpdateTable::ClearAllRecords(const std::string& tableName, CppSQLite3DB* db)
{
	try {
		// Build DELETE statement to clear all records
		std::stringstream sql;
		sql << "DELETE FROM " << tableName;
		
		// Execute the DELETE statement
		db->execDML(sql.str().c_str());
		
		return 0; // Success
		
	} catch (const CppSQLite3Exception& e) {
		// Handle SQLite exceptions
		//std::cout << "SQLite error in ClearAllRecords: " << e.errorMessage() << std::endl;
		return -6; // Error: SQLite exception in clear
	} catch (const std::exception& e) {
		// Handle other exceptions
		std::cout << "General error in ClearAllRecords: " << e.what() << std::endl;
		return -7; // Error: general exception in clear
	}
}
